
#include <ctype.h>

#include <string>
#include <sstream>

#include "utils.h"
#include "procsys.h"

using namespace std;

void SysCpuInfoFragment::loadFromText(const std::string &s)
{
    Properties p;
    p.loadFromText(s);

    processor       = p.value("processor");
    vendor_id       = p.value("vendor_id");
    cpu_family      = p.value("cpu family");
    model           = p.value("model");
    model_name      = p.value("model name");
    stepping        = p.value("stepping");
    microcode       = p.value("microcode");
    cpu_MHz         = p.value("cpu MHz");
    cache_size      = p.value("cache size");
    physical_id     = p.value("physical id");
    siblings        = p.value("siblings");
    core_id         = p.value("core id");
    cpu_cores       = p.value("cpu cores");
    apicid          = p.value("apicid");
    initial_apicid  = p.value("initial apicid");
    fpu             = p.value("fpu");
    fpu_exception   = p.value("fpu_exception");
    cpuid_level     = p.value("cpuid level");
    wp              = p.value("wp");
    flags           = p.value("flags");
    bogomips        = p.value("bogomips");
    clflush_size    = p.value("clflush size");
    cache_alignment = p.value("cache_alignment");
    address_sizes   = p.value("address sizes");
    power_management= p.value("power management");
}

void CpuInfoFileContent::loadFromText(const string &text)
{
    vector<size_t> ivec;
    string::size_type len = text.length();
    size_t beg = 0;
    while (beg < len) {
        string::size_type pos = text.find("processor", beg);
        if (pos != string::npos) {
            ivec.push_back(pos);
            beg = pos + 1;
        } else {
            break;
        }
    }

    vector<size_t>::size_type size = ivec.size();
    vec.resize(size);
    for (vector<size_t>::size_type i = 0; i < size; ++i) {
        if (i != size - 1) {
            vec[i].loadFromText(text.substr(ivec[i], ivec[i+1] - ivec[i]));
        } else {
            vec[i].loadFromText(text.substr(ivec[i]));
        }
    }

}

static inline string get_cpustat_value(const string &text)
{
    string::size_type len = text.length();
    string::size_type a, b;
    bool name = true;
    for (a = 0; a < len; ++a) {
        if (isspace(text[a])) {
            name = false;
        } else if (!name) {
            break;
        }
    }

    for (b = len - 1; b > a; --b) {
        if (!isspace(text[b])) {
            break;
        }
    }

    return text.substr(a, b - a + 1);
}

void SysStatFileContent::loadFromText(const string &text)
{
    istringstream ss(text);
    string line;
    getline(ss, line);
    cpu = get_cpustat_value(line);

    while (ss) {
        getline(ss, line);
        if (line[0] == 'c' && line[1] == 'p' && line[2] == 'u') {
            cpuN.push_back(get_cpustat_value(line));
        } else {
            intr = get_cpustat_value(line);
            break;
        }
    }

    getline(ss, line);
    ctxt = get_cpustat_value(line);

    getline(ss, line);
    btime = get_cpustat_value(line);

    getline(ss, line);
    processes = get_cpustat_value(line);

    getline(ss, line);
    procs_running = get_cpustat_value(line);

    getline(ss, line);
    procs_blocked = get_cpustat_value(line);

    getline(ss, line);
    softirq = get_cpustat_value(line);

}


